﻿using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using Red.Controls.Depot.FileViewItemsProviders;
using Red.Controls.ViewModels;
using Red.Core;
using Red.Core.Containers;

namespace Red.Controls.Depot.ViewModels
{
    public abstract class DepotTreeItemDirectoryBase : DepotTreeItem
    {
        #region Data

        protected readonly DirectoryInfo _dirInfo;

        private List<DirectoryInfo> _subDirsCache;

        #endregion Data

        #region Properties

        public override string Path
        {
            get { return _dirInfo.FullName; }
        }

        public override string BreadcrumbPath
        {
            get { return CreateBreadcrumbPath(); }
        }

        public bool ReadOnlyContent { get; private set; }

        public override bool IsExpandable
        {
            get
            {
                // as we need to enumerate dirs just to check if they are any, store it for later
                _subDirsCache = _dirInfo.EnumerateDirectories().ToList();
                return _subDirsCache.Count > 0;
            }
        }

        #endregion Properties

        #region C-tor
        
        public DepotTreeItemDirectoryBase( DirectoryInfo dirInfo, string title, Canvas image, DepotTreeItem parent, DepotInfo depot, bool isReadOnly )
            : base( title, dirInfo.FullName, image, parent, depot )
        {
            _dirInfo = dirInfo;
            ReadOnlyContent = isReadOnly;
        }

        #endregion C-tor

        #region DepotTreeItem implementation

        public override FileViewItemsProvider GetItemsProvider()
        {
            return new DirectoryFileViewItemsProvider( Path, _depot, ReadOnlyContent );
        }

        #endregion DepotTreeItem implementation

        #region DataItem implementation

        protected override Task EnumerateChildrenAsync( IRangedCollection<DataItem> children )
        {
            try
            {
                children.Clear();

                var subDirs = _subDirsCache ?? _dirInfo.EnumerateDirectories().ToList();
                _subDirsCache = null; // save some memory

                foreach ( var directory in subDirs )
                {
                    try
                    {
                        var item = new DepotTreeItemDirectory( directory, directory.Name, this, _depot, ReadOnlyContent );
                        children.Add( item );
                    }
                    catch ( System.UnauthorizedAccessException e )
                    {
                        // TODO: make a better error handling
                        Debug.Print( e.Message );
                    }
                }
            }
            catch ( IOException e )
            {
                Debug.Print( e.Message );
            }
            catch ( System.UnauthorizedAccessException e )
            {
                Debug.Print( e.Message );
            }

            return Task.CompletedTask;
        }

        #endregion DataItem implementation

        #region Private methods

        string CreateBreadcrumbPath()
        {
            foreach ( DepotInfo.EntryPoint ep in _depot.EntryPoints )
            {
                var root = System.IO.Path.Combine( _depot.RootPath, ep.Path );
                if ( Path.StartsWith( root ) )
                {
                    var marker = "{" + root + ",icon:appbar_resource_group}";
                    return marker + Path.Substring( root.Length );
                }
            }

            return Path; // failsafe
        }
        
        #endregion Private methods
    }

    public class DepotTreeItemDirectoryRoot : DepotTreeItemDirectoryBase
    {
        protected static readonly Canvas _depotIcon;

        public override string PathElement
        {
            get { return _dirInfo.FullName; }
        }
        
        public DepotTreeItemDirectoryRoot( DirectoryInfo dirInfo, string title, DepotTreeItem parent, DepotInfo depot, bool isReadOnly )
            : base( dirInfo, title, _depotIcon, parent, depot, isReadOnly )
        {
        }

        static DepotTreeItemDirectoryRoot()
        {
            _depotIcon = (Canvas)Application.Current.FindResource( "appbar_resource_group" );
        }
    }

    public class DepotTreeItemDirectory : DepotTreeItemDirectoryBase
    {
        public override IEnumerable<RedMenuDataItem> Menu
        {
            get 
            {
                List<RedMenuDataItem> menu = new List<RedMenuDataItem>();
                menu.Add( new RedMenuDataItem( new CommandWrapper( DepotBrowserCommands.AddToFavorites, this ) ) );
                return menu;
            }
        }

        public DepotTreeItemDirectory( DirectoryInfo dirInfo, string title, DepotTreeItem parent, DepotInfo depot, bool isReadOnly )
            : base( dirInfo, title, _folderIcon, parent, depot, isReadOnly )
        {
            PropertyChanged += delegate( object sender, PropertyChangedEventArgs e )
            {
                if ( e.PropertyName == "IsExpanded" )
                {
                    Image = IsExpanded ? _folderOpenIcon : _folderIcon;
                }
            };
        }

        public override IDataObject GetDraggedData()
        {
            return new DataObject( "Red.DepotDirectory", Path );
        }
    }
}